#include "sqlserver.h"

#include <sqlite3.h>
#include <QFile>

#ifdef LINUX
#include <sys/stat.h>
#include <unistd.h>
#endif



/* 此处的宏用于将宏转换为字符串 */
#define TO_STRING(S) #S
#define MACOR_TO_STRING(S) TO_STRING(S)

sqlserver::sqlserver() {
	this->Status = 0;
}

void sqlserver::init_sqlfile()
{
#ifdef LINUX  /*针对Linux平台的代码*/
    // 获取家目录
    const char * HomePath = getenv("HOME");
    if(!HomePath){
        std::cerr << "Not Found The Home Directory!" << std::endl;
        return;
    }
    // 创建目录
    std::string DirPath = std::string(HomePath) + "/.BM";
    if(access(DirPath.c_str(),F_OK) != 0){ // 判断目录是否存在
        mode_t mode = 0755; // 设置目录权限
        if(mkdir(DirPath.c_str(),mode) == -1){
            std::cerr << "Create Dir "<< DirPath << " Faile !" << std::endl;
            return;
        }
    }
    // 创建sqlite文件
    sqlite3 * db;
	std::string DF_Path = DirPath + "/bm_datafile-dev.db"; // bm_datafile-dev.db
    QFile datafile(DF_Path.c_str());
    if(!datafile.exists()){
        std::cout << "Create Datafile !" << std::endl;
        int rc = sqlite3_open(DF_Path.c_str(),&db);
		if(rc != SQLITE_OK){
            std::cerr << "Can't open the datafile " + DF_Path << std::endl;
        }else {
            std::cout << "Init database" << std::endl;
			initDatabase(db);
        }
        sqlite3_close(db);
    }
    datafile.close();

#endif
}

std::string sqlserver::Version()
{
    std::string version=MACOR_TO_STRING(DF_STD_V);
    return version;
}

void sqlserver::initDatabase(sqlite3 * db)
{
	// book_type表
	std::string sql_table = R"(CREATE TABLE book_type (
	id INTEGER PRIMARY KEY AUTOINCREMENT,
	type_name TEXT NOT NULL
);)";
	bool Boo = sql_exec(db,sql_table.c_str(),"Faile to init database");
	if(Boo){
		initBookType(db);
	}

	// book表
	sql_table = R"(CREATE TABLE books (
	isbn TEXT PRIMARY KEY CHECK(length(isbn) = 13),
	name TEXT NOT NULL CHECK(length(name) <= 200),
	author TEXT NOT NULL CHECK(length(author) <= 200),
	publisher TEXT NOT NULL CHECK(length(publisher) <= 200),
	type INTEGER NOT NULL,
	price REAL NOT NULL,
	FOREIGN KEY (type) REFERENCES book_type(id)
);)";
	sql_exec(db,sql_table.c_str(),"Faile to init database");

	// app_config表
	sql_table = R"(CREATE TABLE app_config (
	config TEXT NOT NULL CHECK(length(config) <= 50),
	var TEXT NOT NULL CHECK(length(var) <= 50)
);)";
	Boo = sql_exec(db,sql_table.c_str(),"Faile to init database");
	if(Boo){
		initAppConfig(db); // 初始化软件设置
	}
}

void sqlserver::initAppConfig(sqlite3 *db)
{
	std::string sql_insert = insert_appconfig("DF_STD_V",Version());
	sql_exec(db,sql_insert.c_str(),"Faile to init Tbale: app_config");
}

void sqlserver::initBookType(sqlite3 *db)
{
	// 文学、自然科学、历史、应用技术
	std::string sql_insert = insert_bookType("自然科学");
	sql_exec(db,sql_insert.c_str(),"Faile to init Tbale: book_type!");
	sql_insert = insert_bookType("应用技术");
	sql_exec(db,sql_insert.c_str(),"Faile to init Tbale: book_type!");
	sql_insert = insert_bookType("文学");
	sql_exec(db,sql_insert.c_str(),"Faile to init Tbale: book_type!");
	sql_insert = insert_bookType("历史");
	sql_exec(db,sql_insert.c_str(),"Faile to init Tbale: book_type!");
}

std::string sqlserver::insert_appconfig(std::string var1, std::string var2)
{
	std::string sql_insert = "INSERT INTO app_config (config ,var) VALUES (\"" +
			var1 + "\",\"" + var2 + "\");";
	return sql_insert;
}

std::string sqlserver::insert_bookType(std::string var)
{
	std::string sql_insert = "INSERT INTO book_type (type_name) VALUES (\"" +
			var +"\");";
	return sql_insert;
}

bool sqlserver::sql_exec(sqlite3 *db, const char *sql,const char *Err)
{
	char * zErr;
	int rc=sqlite3_exec(db,sql,NULL,NULL,&zErr);
	if(rc != SQLITE_OK){
		std::cout << zErr << std::endl;
		std::cout << Err << std::endl;
		sqlite3_free(zErr);
		return false;
	}
	return true;
}
